package com.mutouren.modules.datapush.client;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.mutouren.common.log.LogAlias;
import com.mutouren.common.log.LogManager;
import com.mutouren.common.log.Logger;
import com.mutouren.modules.datapush.LocalManager;
import com.mutouren.modules.datapush.base.Charset;
import com.mutouren.modules.datapush.base.Constant;
import com.mutouren.modules.datapush.base.ContentType;
import com.mutouren.modules.datapush.base.DataPushLogAlias;
import com.mutouren.modules.datapush.base.MethodType;
import com.mutouren.modules.datapush.base.Pair;
import com.mutouren.modules.datapush.base.PushClient;
import com.mutouren.modules.datapush.base.PushMessage;
import com.mutouren.modules.datapush.base.PushServer;

public class SimplePushClient implements PushClient {
	
	private String url;
	private String methodAlias;
	private PushServer pushServer;
	
	private final static Logger errorLogger = LogManager.getLogger(LogAlias.SystemError.name());	
	private final static Logger ReceiveCVSLogger = LogManager.getLogger(DataPushLogAlias.DataPushReceiveCVS.name());
	
	public SimplePushClient(String url) {
		this(url, Constant.defaultMethodAlias);
	}
	
	public SimplePushClient(String url, String methodAlias) {
		this(url, methodAlias, Constant.defaultServerAlias);
	}	
	
	public SimplePushClient(String url, String methodAlias, String serverAlias) {
		if (StringUtils.isBlank(url) || StringUtils.isBlank(methodAlias)) {
			throw new IllegalArgumentException("url or methodAlias is blank");
		}		
		
		this.url = url;
		this.methodAlias = methodAlias;
		this.pushServer = LocalManager.getServer(serverAlias);
	}		

	@Override
	public void send(String dataPackage) {
		send(dataPackage, Constant.defaultContentType, Constant.defaultCharset);		
	}

	@Override
	public void send(String dataPackage, ContentType contentType, Charset charset) {
		send("", dataPackage, contentType, charset);		
	}

	@Override
	public void send(String partUrl, String dataPackage) {
		send(partUrl, dataPackage, Constant.defaultContentType, Constant.defaultCharset);	
	}

	@Override
	public void send(String partUrl, String dataPackage, ContentType contentType, Charset charset) {
		if (StringUtils.isBlank(dataPackage)) {
			throw new IllegalArgumentException("dataPackage is blank");
		}
		
		String fullUrl = String.format("%s%s", this.url, StringUtils.isBlank(partUrl) ? "" : partUrl.trim());		
		PushMessage message = new PushMessage(fullUrl, this.methodAlias, dataPackage.trim(), MethodType.POST,
				contentType, charset);	
		
		send(message);
	}
	
	@Override
	public void send(MethodType methodType) {
		send(null, methodType, Constant.defaultCharset);		
	}	

	@Override
	public void send(List<Pair<String, String>> listPair) {
		send(listPair, MethodType.POST, Constant.defaultCharset);		
	}

	@Override
	public void send(List<Pair<String, String>> listPair, MethodType methodType, Charset charset) {
		send("", listPair, methodType, charset);
	}

	@Override
	public void send(String partUrl, List<Pair<String, String>> listPair) {
		send(partUrl, listPair, MethodType.POST, Constant.defaultCharset);		
	}

	@Override
	public void send(String partUrl, List<Pair<String, String>> listPair, MethodType methodType, Charset charset) {
//		if (listPair == null || listPair.size() == 0) {
//			throw new IllegalArgumentException("listPair is null or 0");
//		}
		
		String fullUrl = String.format("%s%s", this.url, StringUtils.isBlank(partUrl) ? "" : partUrl.trim());
		String requestBody = buildBody(listPair, charset);
				
		PushMessage message = new PushMessage(fullUrl, this.methodAlias, requestBody, methodType,
				ContentType.FORM, charset);	
		
		send(message);
	}
	
	private void send(PushMessage message) {
		boolean isException = false;
		try {			
			pushServer.receive(message);
		} catch (Throwable t) {
			isException = true;
			errorLogger.error("SimplePushClient send error", t);	
			throw t;
		} finally {
			writeReceiveLog(message, isException);
		}
	}
	
	private String buildBody(List<Pair<String, String>> listPair, Charset charset) {
		if (listPair == null || listPair.size() == 0) {
			return "";
		}
		
		StringBuilder builder = new StringBuilder();
		for(Pair<String, String> pair : listPair) {
			String key = pair.getKey();
			String value = pair.getValue();
			
			if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) {
				throw new IllegalArgumentException("key or value of listPair is blank");
			}	
			
			try {	
				key = URLEncoder.encode(key.trim(), charset.name);	
				value = URLEncoder.encode(value.trim(), charset.name);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}			
			
			if(builder.length() == 0) {
				builder.append(String.format("%s=%s", key, value));	
			} else {
				builder.append(String.format("&%s=%s", key, value));	
			}
		}
		
		return builder.toString();
	}
	
	/**
	 * 格式: 
	 * logTime,guid,methodAlias,realUrl,requestBody,
	 * methodType,contentType,charset,createTime,isException
	 */
	private void writeReceiveLog(PushMessage message, boolean isException) {		
		String logMsg = String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
				(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS")).format(new Date()),
				message.getGuid(),
				message.getMethodAlias(),
				message.getUrl(),
				message.getRequestBody(),
				
				message.getMethodType(),
				message.getContentType(),
				message.getCharset(),
				(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(message.getCreateTime()),
				isException);
		
		ReceiveCVSLogger.info(logMsg);
	}

}
